﻿namespace HuwmanCode.Diagnostics

open System
open System.Diagnostics
open System.Runtime.InteropServices
open HuwmanCode

[<AutoOpen>]
module ProcessExtension =
    let getParentProcess processId =
        let inline getProc handle initialized =
            let mutable proc = new ProcessEntry32(Size = Marshal.SizeOf(typeof<ProcessEntry32>))
            match initialized with
            | false -> Process32First(handle, &proc) |> Bool.toOption(proc) //Always call Process32First
            | true -> Process32Next(handle, &proc) |> Bool.toOption(proc)   //Process32Next thereafter

        let getProcs handle =
            seq {
                let initialized, finished = ref false, ref false
                while not <| !finished do
                    match getProc handle !initialized with
                    | None -> finished := true; ()
                    | Some p -> initialized := true; yield p }
         
        use handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
        try
            getProcs handle
            |> Seq.tryFind(fun p -> p.ProcessID = processId)
            |> Option.map(fun p -> p.ParentProcessID |> Process.GetProcessById)
        with _ -> None
                    
    type System.Diagnostics.Process with
        /// <summary>
        /// The current process 
        /// </summary>
        static member Current
            with get() = Process.GetCurrentProcess()

        /// <summary>
        /// The parent of the current process
        /// </summary>
        member proc.Parent
            with public get() = getParentProcess proc.Id